<?php

/**
 * Объекты этого класса представляют собой прототипы HTML-форм
 */
class Form implements iForm {
	
	private
		$aFields = array (),
		$aValues = array (),
		$aErrors = array (),
		$oType   = null,
		$prefix  = 0;
	
	/**
	 * Конструктор
	 * @param Type $oType тип, по которому будет строится форма
	 * @param mixed $prefix id объекта или строка "new"
	 */
	public function __construct (Type $oType, $prefix) {
		$this->oType = $oType;
		$this->prefix = $prefix;
	}
	
	/**
	 * Инициализирует форму
	 * @return void
	 */
	public function buildFromType () {
		$aFields = $this->oType->getFields ();
		
		foreach ($aFields as $fieldName => $oField) {
			if (!$oField->isReal ()) {
				continue;
			}

			$this->aFields[$fieldName] = $oField;
			$this->aErrors[$fieldName] = '';
			
			if ($oField->getCharacter () == 'guide' || $oField->getCharacter () == 'multiguide') {
				$this->aValues[$fieldName] = array ();
			} else {
				$this->aValues[$fieldName] = '';
			}
		}
	}

	/**
	 * Добавляет поле в фому
	 * @param Field $oField
	 * @param string $value необязательное значение поля
	 * @param string $error необязательное сообщение об ошибке
	 * @return void
	 */
	public function setField (Field $oField, $value = '', $error = '') {
		if ($oField->isReal () && $oField->getTypeId () == $this->oType->getId ()) {
			$fieldName = $oField->getName();
			$this->aFields[$fieldName] = $oField;
			$this->aValues[$fieldName] = $value;
			$this->aErrors[$fieldName] = $error;
		}
	}
	
	/**
	 * Добавляет значения объекта в поля формы
	 * @param Object $object
	 * @return void
	 */
	public function addObjectValues (Object $object) {
		if ($object->getTypeName () != $this->oType->getName ()) {
			return false;
		}
		
		$aObjectProperties = $object->getValues ();
		
		foreach ($aObjectProperties as $fieldName => $value) {
			$this->aValues[$fieldName] = $value;
		}
	}
	
	/**
	 * Устанавливает значение поля
	 * @param string $fieldName имя поля
	 * @param mixed $value значение поля
	 * @return void
	 */
	public function setValue ($fieldName, $value) {
		$this->aValues[$fieldName] = $value;
	}
	
	/**
	 * Устанавливает сообщение об ошибке поля
	 * @param string $fieldName имя поля
	 * @param string $message сообщение об ошибке
	 * @return void
	 */
	public function setError ($fieldName, $message) {
		$this->aErrors[$fieldName] = $message;
	}
	
	/**
	 * Устанавливает сообщения об ошибках нескольким полям
	 * @param array $aErrors массив: ключ - имя поля, значение - сообщение об ошибке
	 * @return void
	 */
	public function setErrors (array $aErrors) {
		foreach ($aErrors as $fieldName => $error) {
			$this->aErrors[$fieldName] = $error;
		}
	}
	
	/**
	 * Устанавливает значения нескольких полей
	 * @param array $values массив: ключ - имя поля, значение - значение поля
	 * @return void
	 */
	public function setValues (array $values) {
		foreach ($values as $fieldName => $value) {
			$this->aValues[$fieldName] = $value;
		}
	}
	
	/**
	 * Возвращает XML-таблицу прототипа формы
	 * @param DOMDocument $xml
	 * @return DOMElement
	 */
	public function __toXML (DOMDocument $xml) {
		$formNode = $xml->createElement ('form');
		$formNode->setAttribute ('prefix', $this->prefix);
		
		foreach ($this->aFields as $fieldName => $oField) {
			if (!$oField->isEditable ()) {
				continue;
			}
			
			$character = $oField->getCharacter ();
			
			$this->aValues[$fieldName] = str_replace('&', '&amp;', $this->aValues[$fieldName]);
			
			$fieldNode = $xml->createElement ('field');
			$fieldNode->setAttribute ('id', $oField->getId ());
			$fieldNode->setAttribute ('name', $fieldName);
			$fieldNode->setAttribute ('character', $character);
			$fieldNode->appendChild ($xml->createElement ('title', $oField->getTitle ()));
			
			if (($character == 'guide' || $character == 'multiguide') && is_array ($this->aValues[$fieldName])) {
				$aGuidesSelect = FDump::getGuideOptions ($oField->getAddId ());
				
				foreach ($aGuidesSelect as $option) {
					$valueNode = $xml->createElement ('value', $option[1]);
					$valueNode->setAttribute ('id', $option[0]);
					
					if (in_array ($option[0], $this->aValues[$fieldName])) {
						$valueNode->setAttribute ('selected', 'selected');
					}
					
					$fieldNode->appendChild ($valueNode);
				}
			}
			elseif ($character == 'tags' && is_array ($this->aValues[$fieldName])) {
				$fieldNode->appendChild ($xml->createElement ('value', implode (', ', $this->aValues[$fieldName])));
			}
			elseif ($character == 'birthdate') {
				if ($this->aValues[$fieldName] == 0) {
					$this->aValues[$fieldName] = '';
				}
				
				if ($this->aValues[$fieldName] != '') {
					$fieldNode->appendChild ($xml->createElement ('value', date('d.m.Y', $this->aValues[$fieldName])));
				}
			}
			else {
				$fieldNode->appendChild ($xml->createElement ('value', $this->aValues[$fieldName]));	
			}
			$fieldNode->appendChild ($xml->createElement ('help', $oField->getHelp ()));
			$fieldNode->appendChild ($xml->createElement ('error', $this->aErrors[$fieldName]));
			
			$formNode->appendChild ($fieldNode);
		}
		
		return $formNode;
	}

}